<!DOCTYPE html>
<html>

<head>
  <title>Quarkus - Extension for Spring Data API</title>
  <script id="adobe_dtm" src="https://www.redhat.com/dtm.js" type="text/javascript"></script>
  <script src="/assets/javascript/highlight.pack.js" type="text/javascript"></script>
  <META HTTP-EQUIV='Content-Security-Policy' CONTENT="default-src 'none'; script-src 'self' 'unsafe-eval' 'sha256-ANpuoVzuSex6VhqpYgsG25OHWVA1I+F6aGU04LoI+5s=' 'sha256-ipy9P/3rZZW06mTLAR0EnXvxSNcnfSDPLDuh3kzbB1w=' js.bizographics.com https://www.redhat.com assets.adobedtm.com jsonip.com https://ajax.googleapis.com https://www.googletagmanager.com https://www.google-analytics.com https://use.fontawesome.com; style-src 'self' https://fonts.googleapis.com https://use.fontawesome.com; img-src 'self' *; media-src 'self' ; frame-src https://www.googletagmanager.com https://www.youtube.com; frame-ancestors 'none'; base-uri 'none'; object-src 'none'; form-action 'none'; font-src 'self' https://use.fontawesome.com https://fonts.gstatic.com;">
  <META HTTP-EQUIV='X-Frame-Options' CONTENT="DENY">
  <META HTTP-EQUIV='X-XSS-Protection' CONTENT="1; mode=block">
  <META HTTP-EQUIV='X-Content-Type-Options' CONTENT="nosniff">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Quarkus: Supersonic Subatomic Java">
  <meta name="twitter:card" content="summary_large_image">
  <meta name="twitter:site" content="@QuarkusIO"> 
  <meta name="twitter:creator" content="@QuarkusIO">
  <meta property="og:url" content="https://quarkus.io/guides/spring-data-jpa" />
  <meta property="og:title" content="Quarkus - Extension for Spring Data API" />
  <meta property="og:description" content="Quarkus: Supersonic Subatomic Java" />
  <meta property="og:image" content="/assets/images/quarkus_card.png" />
  <link rel="canonical" href="https://quarkus.io/guides/spring-data-jpa">
  <link rel="shortcut icon" type="image/png" href="/favicon.ico" >
  <link rel="stylesheet" href="https://quarkus.io/guides/stylesheet/config.css" />
  <link rel="stylesheet" href="/assets/css/main.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
  <link rel="alternate" type="application/rss+xml"  href="https://quarkus.io/feed.xml" title="Quarkus">
  <script src="https://quarkus.io/assets/javascript/goan.js" type="text/javascript"></script>
  <script src="https://quarkus.io/assets/javascript/hl.js" type="text/javascript"></script>
</head>

<body class="guides">
  <!-- Google Tag Manager (noscript) -->
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-NJWS5L"
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
  <!-- End Google Tag Manager (noscript) -->

  <div class="nav-wrapper">
  <div class="grid-wrapper">
    <div class="width-12-12">
      <input type="checkbox" id="checkbox" />
      <nav id="main-nav" class="main-nav">
  <div class="container">
    <div class="logo-wrapper">
      
        <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_600px_reverse.png" class="project-logo" title="Quarkus"></a>
      
    </div>
    <label class="nav-toggle" for="checkbox">
      <i class="fa fa-bars"></i>
    </label>
    <div id="menu" class="menu">
      <span>
        <a href="/get-started/" class="">Get Started</a>
      </span>
      <span>
        <a href="/guides/" class="active">Guides</a>
      </span>
      <span>
        <a href="/community/" class="">Community</a>
      </span>
      <span>
        <a href="/support/" class="">Support</a>
      </span>
      <span>
        <a href="/blog/" class="">Blog</a>
      </span>
      <span>
        <a href="https://code.quarkus.io" class="button-cta secondary white">Start Coding</a>
      </span>
    </div>
  </div>
      </nav>
    </div>
  </div>
</div>

  <div class="content">
    <div class="guide">
  <div class="width-12-12">
    <h1 class="text-caps">Quarkus - Extension for Spring Data API</h1>
    <div class="hide-mobile toc"><ul class="sectlevel1">
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#solution">Solution</a></li>
<li><a href="#creating-the-maven-project">Creating the Maven project</a></li>
<li><a href="#define-the-entity">Define the Entity</a></li>
<li><a href="#configure-database-access-properties">Configure database access properties</a></li>
<li><a href="#prepare-the-data">Prepare the data</a></li>
<li><a href="#define-the-repository">Define the repository</a></li>
<li><a href="#update-the-jax-rs-resource">Update the JAX-RS resource</a>
<ul class="sectlevel2">
<li><a href="#note-on-spring-web">Note on Spring Web</a></li>
</ul>
</li>
<li><a href="#update-the-test">Update the test</a></li>
<li><a href="#package-and-run-the-application">Package and run the application</a></li>
<li><a href="#run-the-application-as-a-native-binary">Run the application as a native binary</a></li>
<li><a href="#supported-spring-data-jpa-functionalities">Supported Spring Data JPA functionalities</a>
<ul class="sectlevel2">
<li><a href="#what-is-supported">What is supported</a></li>
<li><a href="#what-is-currently-unsupported">What is currently unsupported</a></li>
</ul>
</li>
<li><a href="#important-technical-note">Important Technical Note</a></li>
<li><a href="#more-spring-guides">More Spring guides</a></li>
</ul></div>
    <div>
      <div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>While users are encouraged to use Hibernate ORM with Panache for Relational Database access, Quarkus provides a compatibility layer for
Spring Data JPA repositories in the form of the <code>spring-data-jpa</code> extension.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<i class="fa icon-note" title="Note"></i>
</td>
<td class="content">
<div class="paragraph">
<p>This technology is considered preview.</p>
</div>
<div class="paragraph">
<p>In <em>preview</em>, backward compatibility and presence in the ecosystem is not guaranteed.
Specific improvements might require to change configuration or APIs and plans to become <em>stable</em> are under way.
Feedback is welcome on our <a href="https://groups.google.com/d/forum/quarkus-dev">mailing list</a> or as issues in our <a href="https://github.com/quarkusio/quarkus/issues">GitHub issue tracker</a>.</p>
</div>
<div class="paragraph">
<p>For a full list of possible extension statuses, check our <a href="https://quarkus.io/faq/#extension-status">FAQ entry</a>.</p>
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="prerequisites"><a class="anchor" href="#prerequisites"></a>Prerequisites</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To complete this guide, you need:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>less than 15 minutes</p>
</li>
<li>
<p>an IDE</p>
</li>
<li>
<p>JDK 1.8+ installed with <code>JAVA_HOME</code> configured appropriately</p>
</li>
<li>
<p>Apache Maven 3.6.2+</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="solution"><a class="anchor" href="#solution"></a>Solution</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.</p>
</div>
<div class="paragraph">
<p>Clone the Git repository: <code>git clone <a href="https://github.com/quarkusio/quarkus-quickstarts.git" class="bare">https://github.com/quarkusio/quarkus-quickstarts.git</a></code>, or download an <a href="https://github.com/quarkusio/quarkus-quickstarts/archive/master.zip">archive</a>.</p>
</div>
<div class="paragraph">
<p>The solution is located in the <code>spring-data-jpa-quickstart</code> <a href="https://github.com/quarkusio/quarkus-quickstarts/tree/master/spring-data-jpa-quickstart">directory</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="creating-the-maven-project"><a class="anchor" href="#creating-the-maven-project"></a>Creating the Maven project</h2>
<div class="sectionbody">
<div class="paragraph">
<p>First, we need a new project. Create a new project with the following command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="shell" class="language-shell hljs">mvn io.quarkus:quarkus-maven-plugin:1.7.0.Final:create \
    -DprojectGroupId=org.acme \
    -DprojectArtifactId=spring-data-jpa-quickstart \
    -DclassName="org.acme.spring.data.jpa.FruitResource" \
    -Dpath="/greeting" \
    -Dextensions="spring-data-jpa,resteasy-jsonb,quarkus-jdbc-postgresql"
cd spring-data-jpa-quickstart</code></pre>
</div>
</div>
<div class="paragraph">
<p>This command generates a Maven project with a REST endpoint and imports the <code>spring-data-jpa</code> extension.</p>
</div>
<div class="paragraph">
<p>If you already have your Quarkus project configured, you can add the <code>spring-data-jpa</code> extension
to your project by running the following command in your project base directory:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="bash" class="language-bash hljs">./mvnw quarkus:add-extension -Dextensions="spring-data-jpa"</code></pre>
</div>
</div>
<div class="paragraph">
<p>This will add the following to your <code>pom.xml</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="xml" class="language-xml hljs">&lt;dependency&gt;
    &lt;groupId&gt;io.quarkus&lt;/groupId&gt;
    &lt;artifactId&gt;quarkus-spring-data-jpa&lt;/artifactId&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="define-the-entity"><a class="anchor" href="#define-the-entity"></a>Define the Entity</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Throughout the course of this guide, the following JPA Entity will be used:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.spring.data.jpa;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Fruit {

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private String color;


    public Fruit() {
    }

    public Fruit(String name, String color) {
        this.name = name;
        this.color = color;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="configure-database-access-properties"><a class="anchor" href="#configure-database-access-properties"></a>Configure database access properties</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Add the following properties to <code>application.properties</code> to configure access to a local PostgreSQL instance.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=quarkus_test
quarkus.datasource.password=quarkus_test
quarkus.datasource.jdbc.url=jdbc:postgresql:quarkus_test
quarkus.datasource.jdbc.max-size=8
quarkus.datasource.jdbc.min-size=2
quarkus.hibernate-orm.database.generation=drop-and-create</code></pre>
</div>
</div>
<div class="paragraph">
<p>This configuration assumes that PostgreSQL will be running locally.</p>
</div>
<div class="paragraph">
<p>A very easy way to accomplish that is by using the following Docker command:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-none hljs">docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name quarkus_test -e POSTGRES_USER=quarkus_test -e POSTGRES_PASSWORD=quarkus_test -e POSTGRES_DB=quarkus_test -p 5432:5432 postgres:11.5</code></pre>
</div>
</div>
<div class="paragraph">
<p>If you plan on using a different setup, please change your <code>application.properties</code> accordingly.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="prepare-the-data"><a class="anchor" href="#prepare-the-data"></a>Prepare the data</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To make it easier to showcase some capabilities of Spring Data JPA on Quarkus, some test data should be inserted into the database
by adding the following content to a new file named <code>src/main/resources/import.sql</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="sql" class="language-sql hljs">INSERT INTO fruit(id, name, color) VALUES (1, 'Cherry', 'Red');
INSERT INTO fruit(id, name, color) VALUES (2, 'Apple', 'Red');
INSERT INTO fruit(id, name, color) VALUES (3, 'Banana', 'Yellow');
INSERT INTO fruit(id, name, color) VALUES (4, 'Avocado', 'Green');</code></pre>
</div>
</div>
<div class="paragraph">
<p>Hibernate ORM will execute these queries on application startup.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="define-the-repository"><a class="anchor" href="#define-the-repository"></a>Define the repository</h2>
<div class="sectionbody">
<div class="paragraph">
<p>It is now time to define the repository that will be used to access <code>Fruit</code>.
In a typical Spring Data fashion create a repository like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.spring.data.jpa;

import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface FruitRepository extends CrudRepository&lt;Fruit, Long&gt; {

    List&lt;Fruit&gt; findByColor(String color);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The <code>FruitRepository</code> above extends Spring Data&#8217;s <code>org.springframework.data.repository.CrudRepository</code> which means that all of the latter&#8217;s methods are
available to <code>FruitRepository</code>.
Additionally <code>findByColor</code> is defined whose purpose is to return all Fruit entities that match the specified color.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="update-the-jax-rs-resource"><a class="anchor" href="#update-the-jax-rs-resource"></a>Update the JAX-RS resource</h2>
<div class="sectionbody">
<div class="paragraph">
<p>With the repository in place, the next order of business is to update the JAX-RS resource that will use the <code>FruitRepository</code>. Open <code>FruitResource</code> and change its contents to:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.spring.data.jpa;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.jboss.resteasy.annotations.jaxrs.PathParam;

import java.util.List;
import java.util.Optional;

@Path("/fruits")
public class FruitResource {

    private final FruitRepository fruitRepository;

    public FruitResource(FruitRepository fruitRepository) {
        this.fruitRepository = fruitRepository;
    }

    @GET
    @Produces("application/json")
    public Iterable&lt;Fruit&gt; findAll() {
        return fruitRepository.findAll();
    }


    @DELETE
    @Path("{id}")
    public void delete(@PathParam long id) {
        fruitRepository.deleteById(id);
    }

    @POST
    @Path("/name/{name}/color/{color}")
    @Produces("application/json")
    public Fruit create(@PathParam String name, @PathParam String color) {
        return fruitRepository.save(new Fruit(name, color));
    }

    @PUT
    @Path("/id/{id}/color/{color}")
    @Produces("application/json")
    public Fruit changeColor(@PathParam Long id, @PathParam String color) {
        Optional&lt;Fruit&gt; optional = fruitRepository.findById(id);
        if (optional.isPresent()) {
            Fruit fruit = optional.get();
            fruit.setColor(color);
            return fruitRepository.save(fruit);
        }

        throw new IllegalArgumentException("No Fruit with id " + id + " exists");
    }

    @GET
    @Path("/color/{color}")
    @Produces("application/json")
    public List&lt;Fruit&gt; findByColor(@PathParam String color) {
        return fruitRepository.findByColor(color);
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><code>FruitResource</code> now provides a few REST endpoints that can be used to perform CRUD operation on <code>Fruit</code>.</p>
</div>
<div class="sect2">
<h3 id="note-on-spring-web"><a class="anchor" href="#note-on-spring-web"></a>Note on Spring Web</h3>
<div class="paragraph">
<p>The JAX-RS resource can also be substituted with a Spring Web controller as Quarkus supports REST endpoint definition using Spring controllers.
See the <a href="spring-web">Spring Web guide</a> for more details.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="update-the-test"><a class="anchor" href="#update-the-test"></a>Update the test</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To test the capabilities of <code>FruitRepository</code> proceed to update the content of <code>FruitResourceTest</code> to:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.spring.data.jpa;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.core.IsNot.not;

@QuarkusTest
class FruitResourceTest {

    @Test
    void testListAllFruits() {
        //List all, should have all 3 fruits the database has initially:
        given()
                .when().get("/fruits")
                .then()
                .statusCode(200)
                .body(
                        containsString("Cherry"),
                        containsString("Apple"),
                        containsString("Banana")
                );

        //Delete the Cherry:
        given()
                .when().delete("/fruits/1")
                .then()
                .statusCode(204)
        ;

        //List all, cherry should be missing now:
        given()
                .when().get("/fruits")
                .then()
                .statusCode(200)
                .body(
                        not(containsString("Cherry")),
                        containsString("Apple"),
                        containsString("Banana")
                );

        //Create a new Fruit
        given()
                .when().post("/fruits/name/Orange/color/Orange")
                .then()
                .statusCode(200)
                .body(containsString("Orange"))
                .body("id", notNullValue())
                .extract().body().jsonPath().getString("id");

        //List all, Orange should be present now:
        given()
                .when().get("/fruits")
                .then()
                .statusCode(200)
                .body(
                        not(containsString("Cherry")),
                        containsString("Apple"),
                        containsString("Orange")
                );
    }

    @Test
    void testFindByColor() {
        //Find by color that no fruit has
        given()
                .when().get("/fruits/color/Black")
                .then()
                .statusCode(200)
                .body("size()", is(0));

        //Find by color that multiple fruits have
        given()
                .when().get("/fruits/color/Red")
                .then()
                .statusCode(200)
                .body(
                        containsString("Apple"),
                        containsString("Strawberry")
                );

        //Find by color that matches
        given()
                .when().get("/fruits/color/Green")
                .then()
                .statusCode(200)
                .body("size()", is(1))
                .body(containsString("Avocado"));

        //Update color of Avocado
        given()
                .when().put("/fruits/id/4/color/Black")
                .then()
                .statusCode(200)
                .body(containsString("Black"));

        //Find by color that Avocado now has
        given()
                .when().get("/fruits/color/Black")
                .then()
                .statusCode(200)
                .body("size()", is(1))
                .body(
                        containsString("Black"),
                        containsString("Avocado")
                );
    }

}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The test can be easily run by issuing: <code>./mvnw test</code></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="package-and-run-the-application"><a class="anchor" href="#package-and-run-the-application"></a>Package and run the application</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Quarkus dev mode works with the defined repositories just like with any other Quarkus extension, greatly enhancing your productivity during the dev cycle.
The application can be started in dev mode as usual using:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="bash" class="language-bash hljs">./mvnw compile quarkus:dev</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="run-the-application-as-a-native-binary"><a class="anchor" href="#run-the-application-as-a-native-binary"></a>Run the application as a native binary</h2>
<div class="sectionbody">
<div class="paragraph">
<p>You can of course create a native executable following the instructions of the <a href="building-native-image">this</a> guide.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="supported-spring-data-jpa-functionalities"><a class="anchor" href="#supported-spring-data-jpa-functionalities"></a>Supported Spring Data JPA functionalities</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Quarkus currently supports a subset of Spring Data JPA&#8217;s features, namely the most useful and most commonly used features.</p>
</div>
<div class="paragraph">
<p>An important part of this support is that all repository generation is done at build time thus ensuring that all supported features work correctly in native mode.
Moreover, developers know at build time whether or not their repository method names can be converted to proper JPQL queries.
This also means that if a method name indicates that a field should be used that is not part of the Entity, developers will get
the relevant error at build time.</p>
</div>
<div class="sect2">
<h3 id="what-is-supported"><a class="anchor" href="#what-is-supported"></a>What is supported</h3>
<div class="paragraph">
<p>The following sections described the most important supported features of Spring Data JPA.</p>
</div>
<div class="sect3">
<h4 id="automatic-repository-implementation-generation"><a class="anchor" href="#automatic-repository-implementation-generation"></a>Automatic repository implementation generation</h4>
<div class="paragraph">
<p>Interfaces that extend any of the following Spring Data repositories are automatically implemented:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>org.springframework.data.repository.Repository</code></p>
</li>
<li>
<p><code>org.springframework.data.repository.CrudRepository</code></p>
</li>
<li>
<p><code>org.springframework.data.repository.PagingAndSortingRepository</code></p>
</li>
<li>
<p><code>org.springframework.data.jpa.repository.JpaRepository</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The generated repositories are also registered as beans so they can be injected into any other bean.
Furthermore the methods that update the database are automatically annotated with <code>@Transactional</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="fine-tuning-of-repository-definition"><a class="anchor" href="#fine-tuning-of-repository-definition"></a>Fine tuning of repository definition</h4>
<div class="paragraph">
<p>This allows user defined repository interfaces to cherry-pick methods from any of the supported Spring Data repository interfaces without having to extend those interfaces.
This is particularly useful when for example a repository needs to use some methods from <code>CrudRepository</code> but it&#8217;s undesirable to expose the full list of methods of said interface.</p>
</div>
<div class="paragraph">
<p>Assume for example that a <code>PersonRepository</code> that shouldn&#8217;t extend <code>CrudRepository</code> but would like to use <code>save</code> and <code>findById</code> methods which are defined in said interface.
In such a case, <code>PersonRepository</code> would look like so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">package org.acme.spring.data.jpa;

import org.springframework.data.repository.Repository;

public interface PersonRepository extends Repository&lt;Person, Long&gt; {

    Person save(Person entity);

    Optional&lt;Person&gt; findById(Person entity);
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="customizing-individual-repositories-using-repository-fragments"><a class="anchor" href="#customizing-individual-repositories-using-repository-fragments"></a>Customizing individual repositories using repository fragments</h4>
<div class="paragraph">
<p>Repositories can be enriched with additional functionality or override the default implementation of methods of the supported Spring Data repositories.
This is best shown with an example.</p>
</div>
<div class="paragraph">
<p>A repository fragment is defined as so:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public interface PersonFragment {

    // custom findAll
    List&lt;Person&gt; findAll();

    void makeNameUpperCase(Person person);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The implementation of that fragment looks like this:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">import java.util.List;

import io.quarkus.hibernate.orm.panache.runtime.JpaOperations;

public class PersonFragmentImpl implements PersonFragment {

    @Override
    public List&lt;Person&gt; findAll() {
        // do something here
        return (List&lt;Person&gt;) JpaOperations.findAll(Person.class).list();
    }

    @Override
    public void makeNameUpperCase(Person person) {
        person.setName(person.getName().toUpperCase());
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Then the actual <code>PersonRepository</code> interface to be used would look like:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public interface PersonRepository extends JpaRepository&lt;Person, Long&gt;, PersonFragment {

}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="derived-query-methods"><a class="anchor" href="#derived-query-methods"></a>Derived query methods</h4>
<div class="paragraph">
<p>Methods of repository interfaces that follow the Spring Data conventions can be automatically implemented (unless they fall into one of the unsupported cases listed later on).
This means that methods like the following will all work:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public interface PersonRepository extends CrudRepository&lt;Person, Long&gt; {

    List&lt;Person&gt; findByName(String name);

    Person findByNameBySsn(String ssn);

    Optional&lt;Person&gt; findByNameBySsnIgnoreCase(String ssn);

    boolean existsBookByYearOfBirthBetween(Integer start, Integer end);

    List&lt;Person&gt; findByName(String name, Sort sort);

    Page&lt;Person&gt; findByNameOrderByJoined(String name, Pageable pageable);

    List&lt;Person&gt; findByNameOrderByAge(String name);

    List&lt;Person&gt; findByNameOrderByAgeDesc(String name, Pageable pageable);

    List&lt;Person&gt; findByAgeBetweenAndNameIsNotNull(int lowerAgeBound, int upperAgeBound);

    List&lt;Person&gt; findByAgeGreaterThanEqualOrderByAgeAsc(int age);

    List&lt;Person&gt; queryByJoinedIsAfter(Date date);

    Collection&lt;Person&gt; readByActiveTrueOrderByAgeDesc();

    Long countByActiveNot(boolean active);

    List&lt;Person&gt; findTop3ByActive(boolean active, Sort sort);

    Stream&lt;Person&gt; findPersonByNameAndSurnameAllIgnoreCase(String name, String surname);
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="user-defined-queries"><a class="anchor" href="#user-defined-queries"></a>User defined queries</h4>
<div class="paragraph">
<p>User supplied queries contained in the <code>@Query</code> annotation. For example things like the following all work:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="java" class="language-java hljs">public interface MovieRepository extends CrudRepository&lt;Movie, Long&gt; {

    Movie findFirstByOrderByDurationDesc();

    @Query("select m from Movie m where m.rating = ?1")
    Iterator&lt;Movie&gt; findByRating(String rating);

    @Query("from Movie where title = ?1")
    Movie findByTitle(String title);

    @Query("select m from Movie m where m.duration &gt; :duration and m.rating = :rating")
    List&lt;Movie&gt; withRatingAndDurationLargerThan(@Param("duration") int duration, @Param("rating") String rating);

    @Query("from Movie where title like concat('%', ?1, '%')")
    List&lt;Object[]&gt; someFieldsWithTitleLike(String title, Sort sort);

    @Modifying
    @Query("delete from Movie where rating = :rating")
    void deleteByRating(@Param("rating") String rating);

    @Modifying
    @Query("delete from Movie where title like concat('%', ?1, '%')")
    Long deleteByTitleLike(String title);

    @Modifying
    @Query("update Movie m set m.rating = :newName where m.rating = :oldName")
    int changeRatingToNewName(@Param("newName") String newName, @Param("oldName") String oldName);

    @Modifying
    @Query("update Movie set rating = null where title =?1")
    void setRatingToNullForTitle(String title);

    @Query("from Movie order by length(title)")
    Slice&lt;Movie&gt; orderByTitleLength(Pageable pageable);
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>All methods that are annotated with <code>@Modifying</code> will automatically be annotated with <code>@Transactional</code>.</p>
</div>
</div>
<div class="sect3">
<h4 id="naming-strategies"><a class="anchor" href="#naming-strategies"></a>Naming Strategies</h4>
<div class="paragraph">
<p>Hibernate ORM maps property names using a physical naming strategy and an implicit naming strategy. If you wish to use Spring Boot&#8217;s default naming strategies, the following properties need to be set:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code data-lang="properties" class="language-properties hljs">quarkus.hibernate-orm.physical-naming-strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
quarkus.hibernate-orm.implicit-naming-strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="more-examples"><a class="anchor" href="#more-examples"></a>More examples</h4>
<div class="paragraph">
<p>An extensive list of examples can be seen in the <a href="https://github.com/quarkusio/quarkus/tree/master/integration-tests/spring-data-jpa">integration tests</a> directory which is located inside the Quarkus source code.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="what-is-currently-unsupported"><a class="anchor" href="#what-is-currently-unsupported"></a>What is currently unsupported</h3>
<div class="ulist">
<ul>
<li>
<p>Methods of the <code>org.springframework.data.repository.query.QueryByExampleExecutor</code> interface - if any of these are invoked, a Runtime exception will be thrown.</p>
</li>
<li>
<p>QueryDSL support. No attempt will be made to generate implementations of any of the QueryDSL related repositories.</p>
</li>
<li>
<p>Customizing the base repository for all repository interfaces in the code base.</p>
<div class="ulist">
<ul>
<li>
<p>In Spring Data JPA this is done by registering a class that extends <code>org.springframework.data.jpa.repository.support.SimpleJpaRepository</code> however in Quarkus this class
is not used at all (since all the necessary plumbing is done at build time). Similar support might be added to Quarkus in the future.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Using <code>java.util.concurrent.Future</code> and classes that extend it as return types of repository methods.</p>
</li>
<li>
<p>Native and named queries when using <code>@Query</code></p>
</li>
<li>
<p><a href="https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/asciidoc/jpa.adoc#entity-state-detection-strategies">Entity State-detection Strategies</a>
via <code>EntityInformation</code>.</p>
<div class="ulist">
<ul>
<li>
<p>As of Quarkus 1.6.0, only "Version-Property and Id-Property inspection" is implemented (which should cover most cases).</p>
</li>
<li>
<p>As of Quarkus 1.7.0, <code>org.springframework.data.domain.Persistable</code> is also implemented.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<div class="paragraph">
<p>The Quarkus team is exploring various alternatives to bridging the gap between the JPA and Reactive worlds.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="important-technical-note"><a class="anchor" href="#important-technical-note"></a>Important Technical Note</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Please note that the Spring support in Quarkus does not start a Spring Application Context nor are any Spring infrastructure classes run.
Spring classes and annotations are only used for reading metadata and / or are used as user code method return types or parameter types.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="more-spring-guides"><a class="anchor" href="#more-spring-guides"></a>More Spring guides</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Quarkus has more Spring compatibility features. See the following guides for more details:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="spring-di">Quarkus - Extension for Spring DI</a></p>
</li>
<li>
<p><a href="spring-web">Quarkus - Extension for Spring Web</a></p>
</li>
<li>
<p><a href="spring-security">Quarkus - Extension for Spring Security</a></p>
</li>
<li>
<p><a href="spring-cloud-config-client">Quarkus - Reading properties from Spring Cloud Config Server</a></p>
</li>
<li>
<p><a href="spring-boot-properties">Quarkus - Extension for Spring Boot properties</a></p>
</li>
<li>
<p><a href="spring-cache">Quarkus - Extension for Spring Cache</a></p>
</li>
<li>
<p><a href="spring-scheduled">Quarkus - Extension for Spring Scheduled</a></p>
</li>
</ul>
</div>
</div>
</div>
    </div>
  </div>
</div>

  </div>

  <div class="content project-footer">
  <div class="footer-section">
    <div class="logo-wrapper">
      <a href="/"><img src="/assets/images/quarkus_logo_horizontal_rgb_reverse.svg" class="project-logo" title="Quarkus"></a>
    </div>
  </div>
  <div class="grid-wrapper">
    <p class="grid__item width-3-12">Quarkus is open. All dependencies of this project are available under the <a href='https://www.apache.org/licenses/LICENSE-2.0' target='_blank'>Apache Software License 2.0</a> or compatible license.<br /><br />This website was built with <a href='https://jekyllrb.com/' target='_blank'>Jekyll</a>, is hosted on <a href='https://pages.github.com/' target='_blank'>Github Pages</a> and is completely open source. If you want to make it better, <a href='https://github.com/quarkusio/quarkusio.github.io' target='_blank'>fork the website</a> and show us what you’ve got.</p>

    
      <div class="width-1-12 project-links">
        <span>Navigation</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="/">Home</a></li>
          
            <li><a href="/guides">Guides</a></li>
          
            <li><a href="/community/#contributing">Contribute</a></li>
          
            <li><a href="/faq">FAQ</a></li>
          
            <li><a href="/get-started">Get Started</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Contribute</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://twitter.com/quarkusio">Follow us</a></li>
          
            <li><a href="https://github.com/quarkusio">GitHub</a></li>
          
            <li><a href="/security">Security&nbsp;policy</a></li>
          
        </ul>
      </div>
    
      <div class="width-1-12 project-links">
        <span>Get Help</span>
        <ul class="footer-links width-1-12">
          
            <li><a href="https://groups.google.com/forum/#!forum/quarkus-dev">Forums</a></li>
          
            <li><a href="https://quarkusio.zulipchat.com">Chatroom</a></li>
          
        </ul>
      </div>
    

    
      <div class="width-3-12 more-links">
        <span>Quarkus is made of community projects</span>
        <ul class="footer-links">
          
            <li><a href="https://vertx.io/" target="_blank">Eclipse Vert.x</a></li>
          
            <li><a href="https://microprofile.io" target="_blank">Eclipse MicroProfile</a></li>
          
            <li><a href="https://hibernate.org" target="_blank">Hibernate</a></li>
          
            <li><a href="https://netty.io" target="_blank">Netty</a></li>
          
            <li><a href="https://resteasy.github.io" target="_blank">RESTEasy</a></li>
          
            <li><a href="https://camel.apache.org" target="_blank">Apache Camel</a></li>
          
            <li><a href="https://code.quarkus.io/" target="_blank">And many more...</a></li>
          
        </ul>
      </div>
    
  </div>
</div>
  <div class="content redhat-footer">
  <div class="grid-wrapper">
    <span class="licence">
      <i class="fab fa-creative-commons"></i><i class="fab fa-creative-commons-by"></i> <a href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC by 3.0</a> | <a href="https://www.redhat.com/en/about/privacy-policy">Privacy Policy</a>
    </span>
    <span class="redhat">
      Sponsored by
    </span>
    <span class="redhat-logo">
      <a href="https://www.redhat.com/" target="_blank"><img src="/assets/images/redhat_reversed.svg"></a>
    </span>
  </div>
</div>


  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js" integrity="sha384-8gBf6Y4YYq7Jx97PIqmTwLPin4hxIzQw5aDmUg/DDhul9fFpbbLcLh3nTIIDJKhx" crossorigin="anonymous"></script>
  <script type="text/javascript" src="/assets/javascript/mobile-nav.js"></script>
  <script type="text/javascript" src="/assets/javascript/scroll-down.js"></script>
  <script src="/assets/javascript/satellite.js" type="text/javascript"></script>
  <script src="https://quarkus.io/guides/javascript/config.js" type="text/javascript"></script>
  <script src="/assets/javascript/search-filter.js" type="text/javascript"></script>
  <script src="/assets/javascript/back-to-top.js" type="text/javascript"></script>
</body>

</html>
